package com.jcoinexchange.match.engine;

import lombok.Data;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentSkipListMap;

import static com.jcoinexchange.match.engine.Order.OrderSide.BUY;

@Data
public class OrderBook {

    // TODO: 2025/3/4 设计order 队列结构
    // 限价单：按价格排序的跳表（价格 -> 订单队列）
    private final NavigableMap<Double, List<Order>> bids = new ConcurrentSkipListMap<>(Comparator.reverseOrder());
    private final NavigableMap<Double, List<Order>> asks = new ConcurrentSkipListMap<>();

    // 市价单：独立队列（按时间排序）
    private final Queue<Order> marketBids = new ConcurrentLinkedQueue<>();
    private final Queue<Order> marketAsks = new ConcurrentLinkedQueue<>();

    // 订单ID索引（快速查找撤单）
    private final Map<Long, Order> orderIdIndex = new ConcurrentHashMap<>();

    public void matchLimitOrder(Order order) {
        NavigableMap<Double, OrderQueue> oppositeSide = order.getSide() == BUY ? asks : bids;
        Iterator<Map.Entry<Double, OrderQueue>> it = oppositeSide.entrySet().iterator();

        while (order.getQuantity() > 0 && it.hasNext()) {
            Map.Entry<Double, OrderQueue> entry = it.next();
            double price = entry.getKey();
            // 限价买单价格需 >= 卖单价
            if (order.getSide() == BUY && order.getPrice() < price) break;

            OrderQueue queue = entry.getValue();
            while (!queue.isEmpty()) {
                Order oppositeOrder = queue.peek();
                double tradeQty = Math.min(order.getQuantity(), oppositeOrder.getQuantity());

                // 生成成交记录
//                generateTrade(order, oppositeOrder, tradeQty, price);

                // 更新订单状态
//                updateOrderQuantity(order, oppositeOrder, tradeQty);

                if (oppositeOrder.getQuantity() == 0) {
                    queue.poll();
                    orderIdIndex.remove(oppositeOrder.getOrderId());
                }
                if (order.getQuantity() == 0) break;
            }
            if (queue.isEmpty()) it.remove();
        }

        // 未完全成交的限价单加入订单簿
        if (order.getQuantity() > 0) {
            addToOrderBook(order);
        }
    }

    public void matchMarketOrder(Order order) {
        Queue<Order> oppositeQueue = (order.getSide() == BUY) ? marketAsks : marketBids;
        while (order.getPrice() > 0 && !oppositeQueue.isEmpty()) {
            Order oppositeOrder = oppositeQueue.peek();
            double tradeQty = Math.min(order.getQuantity(), oppositeOrder.getQuantity());
            double price = oppositeOrder.getPrice();  // 市价单按对手方价格成交

            // 生成交易订单
            generateTrade(order, oppositeOrder, tradeQty, price);
            // 更新交易成交数量
            updateOrderQuantity(order, oppositeOrder, tradeQty);

            if (oppositeOrder.getQuantity() == 0) {
                oppositeQueue.poll();
                orderIdIndex.remove(oppositeOrder.getOrderId());
            }
        }
    }

}